import * as cc from "cc";
import { GlobalConfig } from "../../../GlobalConfig";
import NodeUtils from "../../utils/NodeUtils";
import MathUtils from "../../utils/MathUtils";
import { JoystickEvent } from "./events/JoystickEvent";

const { ccclass, menu, property } = cc._decorator;

@ccclass
@menu("扩展组件/Joystick")
/**虚拟摇杆组件 */
export default class Joystick extends cc.Component {
    @property({ type: cc.Node, displayName: "摇杆中间滑块" })
    nodeStick: cc.Node = null;
    @property({ type: cc.Node, displayName: "摇杆底" })
    nodeStickBg: cc.Node = null;
    @property({ type: cc.Node, displayName: "摇杆方向标" })
    nodeDirTag: cc.Node = null;
    @property({ type: cc.Node, displayName: "接收点击事件的节点" })
    nodeTouch: cc.Node = null;

    @property({ displayName: "操作半径" })
    radius: number = 175;
    @property({ displayName: "内圈操作半径" })
    innerRadius: number = 91;
    @property({ displayName: "是否固定位置" })
    isLockPosition: boolean = false;
    @property({ displayName: "是否默认显示轮盘" })
    isShowStick: boolean = true;
    @property({ displayName: "是否允许键盘操作" })
    isOpenKeyboard: boolean = true;

    dir: cc.Vec2 = cc.Vec2.ZERO;
    angle: number = 0;
    stickBgParentUITrans: cc.UITransform;
    stickParentUITrans: cc.UITransform;
    private touchId: number = null;
    private moving: boolean = false;
    private initialPos: cc.Vec3 = null;
    private targetPos: cc.Vec3 = null;
    private isInnerCircle: boolean = false;
    onLoad() {
        this.nodeTouch.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.nodeTouch.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.nodeTouch.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.nodeTouch.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
        this.stickBgParentUITrans = this.nodeStickBg.parent.getComponent(cc.UITransform);
        this.stickParentUITrans = this.nodeStick.parent.getComponent(cc.UITransform);
        this.initialPos = this.nodeStickBg.getWorldPosition().clone();
        this.initKeyboard();
        this.clear();
    }

    /**更新初始位置 */
    updateInialPos(worldPos:cc.Vec3){
        this.initialPos = worldPos.clone();
    }

    onDestroy() {
        this.nodeTouch.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.nodeTouch.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.nodeTouch.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.nodeTouch.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
        this.destoryKeyboard();
    }

    onTouchStart(event: cc.EventTouch) {
        if (!!this.touchId) {
            return;
        }

        let touchPos = event.getUILocation();
        if (!this.isLockPosition) {
            let nodePos = this.stickBgParentUITrans.convertToNodeSpaceAR(cc.v3(touchPos.x, touchPos.y));
            this.nodeStickBg.setPosition(nodePos)
        } else {
            if (!NodeUtils.getWorldRect(this.nodeStickBg).contains(touchPos)) {
                return;
            }
        }
        this.nodeStickBg.active = true;

        this.touchId = event.getID();
        JoystickEvent.ON_JOYSTICK_START.emit();
    }
    onTouchMove(event: cc.EventTouch) {
        if (event.getID() != this.touchId) {
            return;
        }
        const touchPos = event.getUILocation();
        this.targetPos = this.stickParentUITrans.convertToNodeSpaceAR(cc.v3(touchPos.x, touchPos.y));
        this.onMove();
    }

    onMove() {
        //保存向量方向
        this.dir = cc.v2(this.targetPos.x, this.targetPos.y).subtract(cc.Vec2.ZERO).normalize();
        //将小圆限制大圆范围内
        let len = this.targetPos.length();
        if (len > this.radius) {
            this.nodeStick.setPosition(cc.v3(this.dir.x * this.radius, this.dir.y * this.radius, 0));
        } else {
            this.nodeStick.setPosition(cc.v3(this.targetPos.x, this.targetPos.y, 0));
        }
        this.isInnerCircle = len < this.innerRadius;

        //设置弧度
        this.angle = MathUtils.getRadinsByXY(this.targetPos.x, this.targetPos.y)
        this.nodeDirTag.angle = this.angle;
        this.moving = true;
    }

    onTouchEnd(event: cc.EventTouch) {
        if (event.getID() != this.touchId) {
            return;
        }
        this.clear();
        JoystickEvent.ON_JOYSTICK_END.emit();
    }
    onTouchCancel(event: cc.EventTouch) {
        this.onTouchEnd(event);
    }

    update(dt) {
        if (!this.moving) {
            return;
        }
        JoystickEvent.ON_JOYSTICK_MOVE.emit(this.dir, this.angle, this.isInnerCircle);
    }

    clear() {
        this.moving = false;
        this.touchId = null;
        this.dir = cc.Vec2.ZERO;
        this.nodeStick.setPosition(0, 0, 0);
        this.nodeStickBg.setWorldPosition(this.initialPos.x, this.initialPos.y, this.initialPos.z);
        this.nodeStickBg.active = this.isShowStick;
        this.nodeDirTag.angle = 0;
    }

    //#region 键盘事件
    /**键盘按下 */
    private _onKeyDown(event: cc.EventKeyboard) {
        if (event.keyCode === cc.KeyCode.KEY_A || event.keyCode === cc.KeyCode.ARROW_LEFT) {
            this["keyLeft"] = true;
        } else if (event.keyCode === cc.KeyCode.KEY_S || event.keyCode === cc.KeyCode.ARROW_DOWN) {
            this["keyDown"] = true;
        } else if (event.keyCode === cc.KeyCode.KEY_D || event.keyCode === cc.KeyCode.ARROW_RIGHT) {
            this["keyRight"] = true;
        } else if (event.keyCode === cc.KeyCode.KEY_W || event.keyCode === cc.KeyCode.ARROW_UP) {
            this["keyUp"] = true;
        } else {
            return;
        }
        if (!this["keyLeft"] && !this["keyRight"] && !this["keyUp"] && !this["keyDown"]) {
            return;
        }
        this.nodeStickBg.active = true;
        this.keyBoardMove();
    }
    /**键盘抬起 */
    private _onKeyUp(event: cc.EventKeyboard) {
        if (event.keyCode === cc.KeyCode.KEY_A || event.keyCode === cc.KeyCode.ARROW_LEFT) {
            this["keyLeft"] = false;
        } else if (event.keyCode === cc.KeyCode.KEY_S || event.keyCode === cc.KeyCode.ARROW_DOWN) {
            this["keyDown"] = false;
        } else if (event.keyCode === cc.KeyCode.KEY_D || event.keyCode === cc.KeyCode.ARROW_RIGHT) {
            this["keyRight"] = false;
        } else if (event.keyCode === cc.KeyCode.KEY_W || event.keyCode === cc.KeyCode.ARROW_UP) {
            this["keyUp"] = false;
        } else {
            return;
        }
        if (!this["keyLeft"] && !this["keyRight"] && !this["keyUp"] && !this["keyDown"]) {
            this.clear();
            return;
        }
        this.keyBoardMove();
    }

    keyBoardMove() {
        let diffPos = cc.v3(0, 0);
        if (this["keyLeft"]) {
            diffPos = cc.v3(-1, 0, 0)

        } else if (this["keyRight"]) {
            diffPos = cc.v3(1, 0, 0)
        }
        if (this["keyUp"]) {
            diffPos = diffPos.add(cc.v3(0, 1, 0))

        } else if (this["keyDown"]) {
            diffPos = diffPos.add(cc.v3(0, -1, 0))
        }
        if (diffPos.x != 0 || diffPos.y != 0) {
            diffPos.multiplyScalar(this.radius)
            this.targetPos = diffPos;
            this.onMove()
        }
    }

    /**注销键盘事件 */
    destoryKeyboard() {
        if (GlobalConfig.debug && this.isOpenKeyboard) {
            /**注销键盘事件 */
            cc.input.off(cc.Input.EventType.KEY_DOWN, this._onKeyDown, this);
            cc.input.off(cc.Input.EventType.KEY_UP, this._onKeyUp, this);
        }
    }
    /**初始化键盘事件 */
    initKeyboard() {
        if (GlobalConfig.debug && this.isOpenKeyboard) {
            this["keyLeft"] = false;
            this["keyRight"] = false;
            this["keyUp"] = false;
            this["keyDown"] = false;

            cc.input.on(cc.Input.EventType.KEY_DOWN, this._onKeyDown, this);
            cc.input.on(cc.Input.EventType.KEY_UP, this._onKeyUp, this);
        }
    }
    //#endregion 键盘事件
}